
#include "BondType.h"
#include <fstream>
#include "BondDict.h"
#include "BondContainer.h"

/////////////////////////////////////////////////////
// class CBondType
/////////////////////////////////////////////////////

CBondType::CBondType()
: m_Code("")
, m_Name_C("")
, m_Name_E("")
{
}

CBondType::CBondType(char* sCode, char* sName, char* sNameEn)
	: m_Code(sCode)
	, m_Name_C(sName)
	, m_Name_E(sNameEn)
{
}

CBondType::~CBondType(){
	Clear();
}

void CBondType::Clear(){
	m_Code = "";
	m_Name_C = "";
	m_Name_E = "";
	m_list.clear();
}

bool CBondType::operator == (const CBondType& one)
{
	if (m_Code == one.m_Code) return true;
	return false;
}

int CBondType::GetSize(){
	return m_list.size();
}

void CBondType::AddSubType(CBondType& subType){
	m_list.push_back(subType);
}

std::vector<CBondType>* CBondType::GetBondSubTypeList(){
	return &m_list;
}

CBondType* CBondType::GetBondSubType(const char* szSubBondCode)
{
	if(szSubBondCode == NULL)return NULL;
	CBondType stTemp;
	stTemp.m_Code = szSubBondCode;
	vector<CBondType>::iterator itor = find(m_list.begin(), m_list.end(), stTemp);
	if (itor == m_list.end())return NULL;

	if(itor!=m_list.end())
		return &(*itor);
	return NULL;
}
/////////////////////////////////////////////////////
// class CBondTypeList
/////////////////////////////////////////////////////

#define _add_bondtype(strtype){\
	dict.GetBondDict("Bond_Type", strtype, unit);\
	type.m_Code = strtype;\
	type.m_Name_C = unit.selective_content;\
	type.m_Name_E = unit.selective_content_en;\
}

#define _add_bondsubtype(strtype){\
	dict.GetBondDict("Bond_Subtype",strtype,unit);\
	sub.m_Code = strtype;\
	sub.m_Name_C = unit.selective_content;\
	sub.m_Name_E = unit.selective_content_en;\
	type.AddSubType(sub);\
}

CBondTypeList::CBondTypeList()
{
	CBondType type, sub;
    BondDict unit;
	CBondDict& dict = CBondDict::instance();

	//国债
	_add_bondtype("GOV");
	_add_bondsubtype("BGB");
	m_list.push_back(type);
	type.Clear();

	//央票
	_add_bondtype("CBB");
	_add_bondsubtype("SCB");
	m_list.push_back(type);
	type.Clear();

	//地方债
	type.m_Code = "";
	type.m_Name_C = "地方债";
	type.m_Name_E = "Municipal Bond";
	_add_bondsubtype("LLB");
	_add_bondsubtype("TLB");
	m_list.push_back(type);
	type.Clear();

	//金融债
	_add_bondtype("FIN");
	_add_bondsubtype("PBB");
	m_list.push_back(type);
	type.Clear();

	//短融
	_add_bondtype("CPB");
	_add_bondsubtype("CCP");
	_add_bondsubtype("CSP");
	_add_bondsubtype("LCP");
	_add_bondsubtype("LSP");
	m_list.push_back(type);
	type.Clear();

	//中票
	_add_bondtype("MTN");
	_add_bondsubtype("CMN");
	_add_bondsubtype("LMN");
	m_list.push_back(type);
	type.Clear();

	//企业债
	_add_bondtype("EPB");
	_add_bondsubtype("CEB");
	_add_bondsubtype("LEB");
	m_list.push_back(type);
	type.Clear();

	//公司债
	_add_bondtype("COR");
	_add_bondsubtype("COP");
	{
		CBondType *pSub = type.GetBondSubType("COP");
		if (pSub != NULL)
		{
			if (pSub->m_Name_C.length()<=0) pSub->m_Name_C = "公司债";	//补数据库缺失
			if (pSub->m_Name_E.length() <= 0) pSub->m_Name_E = "Corporate Bond";
		}
	}
	_add_bondsubtype("DCO");
	{
		CBondType *pSub = type.GetBondSubType("DCO");
		if (pSub != NULL)
		{
			if (pSub->m_Name_C.length() <= 0) pSub->m_Name_C = "非公开公司债";	//补数据库缺失
			if (pSub->m_Name_E.length() <= 0) pSub->m_Name_E = "Private Placement Corporate Bond";
		}
	}
	m_list.push_back(type);
	type.Clear();

	//PPN
	type.m_Code = "";
	type.m_Name_C = "PPN";
	type.m_Name_E = "PPN";

	sub.m_Code = "PPN";
	sub.m_Name_C = "PPN";
	sub.m_Name_E = "PPN";	//硬写代码，字典显示“私募债” 暂无法动字典 20160510
	type.AddSubType(sub);

	m_list.push_back(type);
	type.Clear();
	
	//ABS
	type.m_Code = "";
	type.m_Name_C = "ABS";
	type.m_Name_E = "ABS";
	_add_bondsubtype("AMP");
	_add_bondsubtype("LBS");
	_add_bondsubtype("CBS");
	_add_bondsubtype("MBS");
	m_list.push_back(type);
	type.Clear();

	//金融机构债
	type.m_Code = "";
	type.m_Name_C = "金融机构债";
	type.m_Name_E = "Financial Institution Bond";
	_add_bondsubtype("PSB");
	_add_bondsubtype("TET");//二级资本工具
	_add_bondsubtype("CBB");
	_add_bondsubtype("CSB");
	_add_bondsubtype("CXB");
	_add_bondsubtype("NCB");
	_add_bondsubtype("SFB");
	_add_bondsubtype("SEB");
	_add_bondsubtype("SSB");
	_add_bondsubtype("SES");
	_add_bondsubtype("HJB");
	m_list.push_back(type);
	type.Clear();

	//集合债
	type.m_Code = "";
	type.m_Name_C = "集合债";
	type.m_Name_E = "Collective";
	_add_bondsubtype("CCB");
	_add_bondsubtype("COB");
	m_list.push_back(type);
	type.Clear();

	//可转债
	type.m_Code = "";
	type.m_Name_C = "可转债";
	type.m_Name_E = "Convertible Bond";
	_add_bondsubtype("SCV");
	_add_bondsubtype("CVB");
	m_list.push_back(type);
	type.Clear();
	
	//NCD
	type.m_Code = "";
	type.m_Name_C = "NCD";
	type.m_Name_E = "NCD";
	_add_bondsubtype("MCD");
	_add_bondsubtype("SPD");
	_add_bondsubtype("SHD");
	_add_bondsubtype("CCD");
	_add_bondsubtype("RRD");
	_add_bondsubtype("RTD");
	_add_bondsubtype("FRD");
	_add_bondsubtype("OTD");
	m_list.push_back(type);
	type.Clear();

	//CRM
	type.m_Code = "";
	type.m_Name_C = "CRM";
	type.m_Name_E = "CRM";
	_add_bondsubtype("CRM");
	_add_bondsubtype("CLN");
	m_list.push_back(type);
	type.Clear();

	//其他
	type.m_Code = "";
	type.m_Name_C = "其他";
	type.m_Name_E = "Others";
	_add_bondsubtype("RAB");
	_add_bondsubtype("INT");
	_add_bondsubtype("PDB");
	m_list.push_back(type);
	type.Clear();
}

CBondTypeList::~CBondTypeList()
{
	m_list.clear();
}

int CBondTypeList::GetSize()
{
	return m_list.size();
}

std::vector<CBondType>* CBondTypeList::GetBondTypeList()
{
	return &m_list;
}

CBondType* CBondTypeList::GetBondSubTypeList(const char* strNameC)
{
	std::vector<CBondType>::iterator it;
	for(it = m_list.begin(); it != m_list.end(); it ++)
	{
		if(strcmp(it->m_Name_C.c_str(), strNameC) == 0)
		{
			return &(*it);
		}
	}
	return NULL;
}

CBondType* CBondTypeList::GetBondSubType(const char* szSubBondCode)
{
	if(szSubBondCode == NULL)
		return NULL;
	CBondType* pSubType = NULL;
	std::vector<CBondType>::iterator it;
	for(it = m_list.begin(); it != m_list.end(); it ++)
	{
		CBondType* pBondType = &(*it);
		if(pBondType==NULL) 
			continue;

		pSubType = pBondType->GetBondSubType(szSubBondCode);
		if(pSubType)
			break;
	}

	return pSubType;
}

//-------------------------------------------------------------------------------------------
CBondTypeV2::CBondTypeV2()
{

}

CBondTypeV2::CBondTypeV2(const char*pszEnName,const char*pszCnName)
{
	m_umapSubType.clear();

	if (pszCnName)
		m_Name_C = pszCnName;
	if (pszEnName)
		m_Name_E = pszEnName;
}

CBondTypeV2::~CBondTypeV2()
{

}

void CBondTypeV2::Clear()
{
	m_Name_C.clear();
	m_Name_E.clear();

	m_umapSubType.clear();
}

unsigned int CBondTypeV2::Size()
{
	return m_umapSubType.size();
}

void CBondTypeV2::Add(CBondType &subType)
{
	m_umapSubType.insert({ subType.m_Code, subType });
}

void CBondTypeV2::Add(CBondType subType)
{
	m_umapSubType.insert({ subType.m_Code, subType });
}

const CBondTypeV2::UMAP_SUBTYPE& CBondTypeV2::GetMap()
{
	return m_umapSubType;
}

const CBondType& CBondTypeV2::GetSubType(const char*pszSubTypeCode)
{
	static const CBondType bst;

	if (!pszSubTypeCode)
		return bst;

	UMAP_SUBTYPE::iterator itrFind = m_umapSubType.find(std::string(pszSubTypeCode));

	return itrFind == m_umapSubType.end() ? bst : itrFind->second;
}

#define BUILD_SUBTYPE(szSubType,emBondTypex)\
	dict.GetBondDict("Bond_Subtype", szSubType, unit);\
	type.Add(CBondType(szSubType, unit.selective_content_en, unit.selective_content));\
	m_umapCode2Type.insert({ szSubType ,emBondTypex});

CBondTypeMap::CBondTypeMap()
{
	CBondType sub;
	CBondTypeV2 type;
	BondDict unit;
	CBondDict& dict = CBondDict::instance();

	type.Clear();
	type.m_Name_C = "国债"; //TODO: 中文可能有问题
	type.m_Name_E = "Country";
	BUILD_SUBTYPE("BGB", CBondContainer::BondCountry);
	BUILD_SUBTYPE("SGB", CBondContainer::BondCountry);
	BUILD_SUBTYPE("EGB", CBondContainer::BondCountry);
	m_umapType2Body.insert({ CBondContainer::BondCountry, type });
	
	type.Clear();
	type.m_Name_C = "央票";
	type.m_Name_E = "Center";
	BUILD_SUBTYPE("SCB", CBondContainer::BondCenter);
	m_umapType2Body.insert({ CBondContainer::BondCenter, type });
	
	type.Clear();
	type.m_Name_C = "政金债";
	type.m_Name_E = "Finance";
	BUILD_SUBTYPE("PBB", CBondContainer::BondFinance);
	BUILD_SUBTYPE("PSB", CBondContainer::BondFinance);
	m_umapType2Body.insert({ CBondContainer::BondFinance, type });

	type.Clear();
	type.m_Name_C = "地方债";
	type.m_Name_E = "Local";
	BUILD_SUBTYPE("LLB", CBondContainer::BondLocal);
	BUILD_SUBTYPE("TLB", CBondContainer::BondLocal);
	m_umapType2Body.insert({ CBondContainer::BondLocal, type });
	
	type.Clear();
	type.m_Name_C = "短融";
	type.m_Name_E = "Short";
	BUILD_SUBTYPE("CCP", CBondContainer::BondShort);
	BUILD_SUBTYPE("SSB", CBondContainer::BondShort);
	BUILD_SUBTYPE("CSP", CBondContainer::BondShort);
	BUILD_SUBTYPE("LCP", CBondContainer::BondShort);
	BUILD_SUBTYPE("LSP", CBondContainer::BondShort);
	m_umapType2Body.insert({ CBondContainer::BondShort, type });

	type.Clear();
	type.m_Name_C = "中票";
	type.m_Name_E = "China";
	BUILD_SUBTYPE("CMN", CBondContainer::BondChina);
	BUILD_SUBTYPE("LMN", CBondContainer::BondChina);
	m_umapType2Body.insert({ CBondContainer::BondChina, type });

	type.Clear();
	type.m_Name_C = "企业债";
	type.m_Name_E = "Enterpr";	
	BUILD_SUBTYPE("CCB", CBondContainer::BondEnterpr);
	BUILD_SUBTYPE("COB", CBondContainer::BondEnterpr);
	BUILD_SUBTYPE("RAB", CBondContainer::BondEnterpr);
	BUILD_SUBTYPE("CEBENT", CBondContainer::BondEnterpr);
	BUILD_SUBTYPE("LEBENT", CBondContainer::BondEnterpr);
	m_umapType2Body.insert({ CBondContainer::BondEnterpr, type });
	
	type.Clear();
	type.m_Name_C = "公司债";
	type.m_Name_E = "Cop";
	BUILD_SUBTYPE("CEBCOP", CBondContainer::BondCOP);
	BUILD_SUBTYPE("LEBCOP", CBondContainer::BondCOP);
	BUILD_SUBTYPE("PPNCOP", CBondContainer::BondCOP);
	m_umapType2Body.insert({ CBondContainer::BondCOP, type });

	type.Clear();
	type.m_Name_C = "PPN"; //PPN + NULL;
	type.m_Name_E = "PPN";
	type.Add(CBondType("PPNNULL", "PPN", "PPN"));
	m_umapCode2Type.insert({ "PPNNULL", CBondContainer::BondPPN });
	m_umapType2Body.insert({ CBondContainer::BondPPN, type });

	type.Clear();
	type.m_Name_C = "NCD";
	type.m_Name_E = "NCD";
	BUILD_SUBTYPE("MCD", CBondContainer::BondNCD);
	BUILD_SUBTYPE("SPD", CBondContainer::BondNCD);
	BUILD_SUBTYPE("SHD", CBondContainer::BondNCD);
	BUILD_SUBTYPE("CCD", CBondContainer::BondNCD);
	BUILD_SUBTYPE("RRD", CBondContainer::BondNCD);
	BUILD_SUBTYPE("RTD", CBondContainer::BondNCD);
	BUILD_SUBTYPE("FRD", CBondContainer::BondNCD);
	BUILD_SUBTYPE("OTD", CBondContainer::BondNCD);
	m_umapType2Body.insert({ CBondContainer::BondNCD, type });
	
	type.Clear();
	type.m_Name_C = "ABS";
	type.m_Name_E = "Asset Backed";
	BUILD_SUBTYPE("AMP", CBondContainer::BondABS);
	BUILD_SUBTYPE("LBS", CBondContainer::BondABS);
	BUILD_SUBTYPE("CBS", CBondContainer::BondABS);
	BUILD_SUBTYPE("MBS", CBondContainer::BondABS);
	m_umapType2Body.insert({ CBondContainer::BondABS, type });

	type.Clear();
	type.m_Name_C = "CRM";
	type.m_Name_E = "CRM";
	BUILD_SUBTYPE("CRM", CBondContainer::BondCRM);
	BUILD_SUBTYPE("CLN", CBondContainer::BondCRM);
	m_umapType2Body.insert({ CBondContainer::BondCRM, type });
}

UINT CBondTypeMap::GetTypeEm(const char*pszSubType, const char*pszEntCor/* =NULL */)
{
	if (!pszSubType || strlen(pszSubType) == 0)
		return CBondContainer::BondOther;

	UMAP_CODE2TYPE::iterator itrFind = m_umapCode2Type.find(std::string(pszSubType));
	if (itrFind != m_umapCode2Type.end())
		return itrFind->second;

	std::string sKey = pszSubType;
	if (!pszEntCor || strlen(pszEntCor) == 0)
	{
		sKey += "NULL";
	}
	else if (!pszEntCor || strlen(pszEntCor) > 0)
	{
		sKey += pszEntCor;
	}

	if (sKey.compare(pszSubType) != 0)
	{
		UMAP_CODE2TYPE::iterator itrFindx = m_umapCode2Type.find(std::string(sKey));
		if (itrFindx != m_umapCode2Type.end())
			return itrFindx->second;
	}

	return CBondContainer::BondOther;
}

CBondTypeMap::~CBondTypeMap()
{

}

CBondTypeMap CBondTypeMap::instance()
{
	static CBondTypeMap s_btm;
	return s_btm;
}

UINT CBondTypeMap::Size()
{
	return m_umapType2Body.size();
}

const CBondTypeMap::UMAP_TYPE2BODY &CBondTypeMap::GetMap()
{
	return m_umapType2Body;
}

const CBondTypeV2 &CBondTypeMap::GetType(UINT nCode)
{
	static const CBondTypeV2 btv2("Other","其它");

	UMAP_TYPE2BODY::iterator itrFind = m_umapType2Body.find(nCode);

	return itrFind == m_umapType2Body.end() ? btv2 : itrFind->second;
}

const CBondTypeV2 &CBondTypeMap::GetType(const char*pszSubType, const char*pszEntCor /* = NULL */)
{
	return GetType(GetTypeEm(pszSubType, pszEntCor));
}